package com.heima.wemedia.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.exception.CustException;
import com.heima.file.service.FileStorageService;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.threadlocal.WmThreadLocalUtils;
import com.heima.model.wemedia.dtos.WmMaterialDTO;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.wemedia.mapper.WmMaterialMapper;
import com.heima.wemedia.mapper.WmNewsMaterialMapper;
import com.heima.wemedia.service.WmMaterialService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Slf4j
@Service
public class WmMaterialServiceImpl extends ServiceImpl<WmMaterialMapper, WmMaterial> implements WmMaterialService {

    @Autowired
    private FileStorageService fileStorageService;

    @Value("${file.oss.web-site}")
    private String webSite;

    @Value("${file.oss.prefix}")
    private String prefix;

    @Autowired
    private WmNewsMaterialMapper newsMaterialMapper;

    /**
     * 图片上传功能 ***
     * @param dto //MultipartFile是SpringMVC提供简化上传操作的工具类。
     * @return
     */
    @Override
    public ResponseResult<WmMaterial> uploadPicture(MultipartFile dto) {

        //1.校验参数
        if (dto.getSize() == 0 || dto == null) {
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST,"数据不存在");
        }
        //1.2 判断用户是否登陆
        WmUser wmUser = WmThreadLocalUtils.getUser();
        if (wmUser ==null) {
            CustException.cust(AppHttpCodeEnum.NEED_LOGIN,"需要先登录");
        }
        //1.3 判断文件格式是否正确
        String filename = dto.getOriginalFilename();
        if (!checkFileSuffix(filename)){
            CustException.cust(AppHttpCodeEnum.PARAM_IMAGE_FORMAT_ERROR,"图片格式有误");
        }

        //2.上传图片到OSS
        String pathUrl = null;
        try {
            String name1 = UUID.randomUUID().toString().replaceAll("-", "");
            String suffix = filename.substring(filename.lastIndexOf("."));
            //上传并获取图片访问路径
            pathUrl = fileStorageService.store(prefix, name1 + suffix, dto.getInputStream());
            log.info("阿里云OSS 文件 fileId: {}",pathUrl);
        } catch (IOException e) {
            e.printStackTrace();
            log.error("阿里云文件上传失败 uploadPicture error: {}", e);
            CustException.cust(AppHttpCodeEnum.SERVER_ERROR,"服务器繁忙请稍后重试");
        }

        //3. 封装保存到素材表中
        WmMaterial wmMaterial = new WmMaterial();

        wmMaterial.setUserId(wmUser.getId());
        wmMaterial.setUrl(pathUrl);
        wmMaterial.setType((short) 0);
        wmMaterial.setIsCollection((short) 0);
        wmMaterial.setCreatedTime(new Date());

        this.save(wmMaterial);
        //设置url返回给前端
        wmMaterial.setUrl(webSite+pathUrl);

        //4.返回结果
        return ResponseResult.okResult(wmMaterial);
    }
    //检查文件后缀
    private boolean checkFileSuffix(String filename) {
        if (StringUtils.isBlank(filename)) {
            CustException.cust(AppHttpCodeEnum.PARAM_REQUIRE,"文件路径为空");
        }
        Boolean flag = false;
        List<String> list = Arrays.asList("jpg", "jpeg", "png", "gif");
        List<String> collect = list.stream().filter(string -> filename.endsWith(string)).collect(Collectors.toList());
        if (collect.size()>0) {
            flag = true;
        }
        return flag;
    }

    /**
     * 加载素材列表
     * @param dto
     * @return
     */
    @Override
    public ResponseResult findList(WmMaterialDTO dto) {
        //1.校验参数
        if (dto==null) {
            CustException.cust(AppHttpCodeEnum.PARAM_REQUIRE,"缺少参数");
        }

        //判断用户是否登陆
        Integer wmUserId = WmThreadLocalUtils.getUser().getId();
        if (wmUserId==null) {
            CustException.cust(AppHttpCodeEnum.NEED_LOGIN,"请先登录");
        }


        dto.checkParam();

        //2.构建查询条件

        Page<WmMaterial> wmPage = new Page<>(dto.getPage(),dto.getSize());

        LambdaQueryWrapper<WmMaterial> queryWrapper = Wrappers.<WmMaterial>lambdaQuery();

        //2.1 收藏 (前端收藏图片里没有取消按钮，需要把收藏与未被收藏的图片在全部里展示出来)
        if (dto.getIsCollection()!=null && dto.getIsCollection() == 1) {
            queryWrapper.eq(WmMaterial::getIsCollection,dto.getIsCollection());
        }

        //2.2 判断用户是否登陆，根据登陆用户的ID查询素材表
        WmUser wmUser = WmThreadLocalUtils.getUser();
        if (wmUser==null) {
            CustException.cust(AppHttpCodeEnum.NEED_LOGIN,"请先登录");
        }
        queryWrapper.eq(WmMaterial::getUserId,wmUser.getId());

        //2.3 根据创建时间降序排列
        queryWrapper.orderByDesc(WmMaterial::getCreatedTime);


        //3.执行查询

        IPage<WmMaterial> result = this.page(wmPage, queryWrapper);

        //4.封装结果返回

        //result.getRecords().stream().filter(wm -> wm.setUrl(webSite + wm.getUrl()));
        //设置url返回给前端
        List<WmMaterial> wms = result.getRecords();
        for (WmMaterial wm : wms) {
            wm.setUrl(webSite+wm.getUrl());
        }

        return new PageResponseResult(dto.getPage(),dto.getSize(),result.getTotal(),wms);


    }

    /**
     * 删除图片功能
     * @param id
     * @return
     */
    @Override
    public ResponseResult deletePicById(Integer id) {
        //1.校验参数

        if (id==null) {
            CustException.cust(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //判断用户是否登陆
        Integer wmUserId = WmThreadLocalUtils.getUser().getId();
        if (wmUserId==null) {
            CustException.cust(AppHttpCodeEnum.NEED_LOGIN,"请先登录");
        }

        //通过关联表查询该素材是否被引用
        WmNewsMaterial wmNewsMaterial = newsMaterialMapper.selectById(id);
        if (wmNewsMaterial!=null) {
            if (wmNewsMaterial.getType()!=null) {
                CustException.cust(AppHttpCodeEnum.NO_OPERATOR_AUTH,"该图片已被引用");
            }
        }
        //判断素材表中是否存在该数据
        WmMaterial wmMaterial = this.getById(id);
        if (wmMaterial==null) {
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        //2.从OSS中删除图片

        String path = wmMaterial.getUrl();
        String  url  = webSite + path;
        fileStorageService.delete(url);

        //3.从素材中删除对应数据

        boolean flag = this.removeById(id);

        //4.返回结果

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }


    /**
     * 图片的收藏与取消
     * @param id  素材id
     * @param type CANCEL_COLLECT_MATERIAL 取消     COLLECT_MATERIAL 收藏
     * @return
     */
    @Override
    public ResponseResult updateStatus(Integer id, Short type) {
        //1.校验参数
        if (id==null) {
            CustException.cust(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //判断用户是否登陆
        Integer wmUserId = WmThreadLocalUtils.getUser().getId();
        if (wmUserId==null) {
            CustException.cust(AppHttpCodeEnum.NEED_LOGIN,"请先登录");
        }

        //2.查询数据，修改状态
        WmMaterial wmMaterial = this.getById(id);
        if (wmMaterial==null) {
            CustException.cust(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        wmMaterial.setIsCollection(type);

        boolean b = this.updateById(wmMaterial);

        //返回数据

        return ResponseResult.okResult();

    }


}
